package br.ufpi.hu.prescricao.dao;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.ejb.Stateless;
import javax.naming.NamingException;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Order;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.persistence.metamodel.EntityType;
import javax.persistence.metamodel.Metamodel;

import br.ufpi.hu.prescricao.model.Laudo;
import br.ufpi.hu.prescricao.model.Usuario;

@Stateless
public class LaudoDAO extends GenericDAO<Laudo> {

	public LaudoDAO() {
		super(Laudo.class);
	}
	
	public EntityManager getEntityManager() {
		return em;
	}

	@Override
	public void save(Laudo entity) {

		entity.cria();

		super.save(entity);
	}

	@Override
	public List<Laudo> findAll(Map<String, String> orderByParams,
			Map<String, Object> restriction) {

		return super.findAll(orderByParams,restriction);

	}

	public List<Laudo> findAllByUser(Usuario usuarioDaSessao,
			Map<String, String> orderByParams) throws NamingException {

		Map<String, Object> restriction = new HashMap<String, Object>();

		restriction.put("usuarioDaSessao", usuarioDaSessao);

		return super.findAll(orderByParams,restriction);

	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public List<Laudo> findAllFiltroDataPaciente(Usuario usuarioDaSessao,	Map<String, String> ordenacao, Date dataInicial, Date dataFinal, Integer pacienteId, int maxResult, int startPosition) {
		
		CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
		Root root = cq.from(entityClass);
		cq.select(root);

		Metamodel m = em.getMetamodel();
		EntityType<Laudo> sol = m.entity(Laudo.class);
		
		List<Order> orderList = new ArrayList<Order>();

		//ordenacao
		
		for (String param : ordenacao.values()) {

			String key = getKeyByValue(ordenacao,param);
			Order order;

			if (param.equals("asc")) {
				order = em.getCriteriaBuilder().asc(root.get(sol.getSingularAttribute(key)));				
			}
			else if (param.equals("desc")) {
				order = em.getCriteriaBuilder().desc(root.get(sol.getSingularAttribute(key)));
			}
			else {
				//erro!
				throw new RuntimeException();
			}
			
			orderList.add(order);
		}
		
		if (orderList.size() != 0) {
			cq.orderBy(orderList);
		}
		
		//restricoes		
		List<Predicate> predicates = new ArrayList<Predicate>();
		
				
		if (usuarioDaSessao!=null){
			
			predicates.add(em.getCriteriaBuilder().equal(root.get("usuarioDaSessao"), usuarioDaSessao));
				
		}
		
		if (dataInicial!=null) {
			predicates.add(em.getCriteriaBuilder().greaterThanOrEqualTo(root.get("dataDeCriacao"), dataInicial));
		
		}
		
		if (dataFinal!=null) {
			
			predicates.add(em.getCriteriaBuilder().lessThanOrEqualTo(root.get("dataDeCriacao"), dataFinal));
			
		}
		
		if (pacienteId!=null) {
			
			predicates.add(em.getCriteriaBuilder().equal(root.get("idPacienteAghu"), pacienteId));
			
		}
		
		cq.where(em.getCriteriaBuilder().and(predicates.toArray(new Predicate[predicates.size()])));
		
		TypedQuery<Laudo> t = em.createQuery(cq);
		
		if (maxResult!=0)
			t.setMaxResults(maxResult);
		t.setFirstResult(startPosition);
		
		return t.getResultList();
		
	}
	
}